package com.ruoyi.framework.security.filter;

import com.abth.openapi.domain.OpapiApp;
import com.abth.openapi.service.IOpapiAppService;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@Component
public class OpenApiAuthenticationFilter extends OncePerRequestFilter {

    private static final Logger log = LoggerFactory.getLogger(OpenApiAuthenticationFilter.class);

    @Autowired
    private IOpapiAppService opapiAppService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {

        String uri = request.getRequestURI();

        // 只处理开放API路径
        if (!uri.startsWith("/open/api/")) {
            chain.doFilter(request, response);
            return;
        }

        try {
            // 1. 获取认证信息
            String appKey = request.getHeader("X-App-Key");
            String appSecret = request.getHeader("X-App-Secret");

            if (StringUtils.isEmpty(appKey) || StringUtils.isEmpty(appSecret)) {
                writeErrorResponse(response, 401, "Missing AppKey or AppSecret");
                return;
            }

            // 2. 验证应用
            OpapiApp app = opapiAppService.selectOpapiAppByAppKey(appKey);
            if (app == null) {
                writeErrorResponse(response, 401, "Invalid AppKey");
                return;
            }

            if (!"0".equals(app.getStatus())) {
                writeErrorResponse(response, 401, "App is disabled");
                return;
            }

            if (!appSecret.equals(app.getAppSecret())) {
                writeErrorResponse(response, 401, "Invalid AppSecret");
                return;
            }

            // 3. IP白名单验证（可选）
            if (StringUtils.isNotEmpty(app.getIpWhitelist())) {
                String clientIp = getClientIp(request);
                if (!isIpInWhitelist(clientIp, app.getIpWhitelist())) {
                    writeErrorResponse(response, 401, "IP not in whitelist");
                    return;
                }
            }

            // 4. 创建认证令牌（如果需要，可以在这里设置Spring Security的Authentication）
            // 这样在Controller中可以通过SecurityContext获取认证信息
            OpenApiAuthenticationToken authentication =
                    new OpenApiAuthenticationToken(appKey, app.getAppName());
            SecurityContextHolder.getContext().setAuthentication(authentication);

            // 5. 将应用信息存入请求属性
            request.setAttribute("appKey", appKey);
            request.setAttribute("appName", app.getAppName());
            log.info("开放API认证通过 - 应用[{}]访问[{}]", app.getAppName(), uri);
            chain.doFilter(request, response);

        } catch (Exception e) {
            log.error("开放API认证异常", e);
            writeErrorResponse(response, 500, "Server error: " + e.getMessage());
        }
    }

    private void writeErrorResponse(HttpServletResponse response, int code, String message) throws IOException {
        response.setStatus(code);
        response.setContentType("application/json;charset=utf-8");

        Map<String, Object> result = new HashMap<>();
        result.put("code", code);
        result.put("msg", message);
        result.put("timestamp", System.currentTimeMillis());

        response.getWriter().write(JSON.toJSONString(result));
    }

    private String getClientIp(HttpServletRequest request) {
        return IpUtils.getIpAddr(request);
    }

    private boolean isIpInWhitelist(String ip, String whitelist) {
        // IP白名单验证逻辑...
        return Arrays.asList(whitelist.split(",")).contains(ip);
    }
}